package com.wangxinenpu.springbootdemo.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.wangxinenpu.springbootdemo.dao.mapper.SysSystemProcessMapper;
import com.wangxinenpu.springbootdemo.dataobject.model.SysSystem;
import com.wangxinenpu.springbootdemo.dataobject.model.SysSystemProcess;
import com.wangxinenpu.springbootdemo.dataobject.vo.BPMNDTO;
import com.wangxinenpu.springbootdemo.dataobject.vo.process.ProcessDefinitionDetailVO;
import com.wangxinenpu.springbootdemo.dataobject.vo.process.ProcessInstanceVO;
import com.wangxinenpu.springbootdemo.dataobject.vo.task.AjaxResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.impl.util.CollectionUtil;
import org.activiti.engine.runtime.ProcessInstance;
import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.security.core.parameters.P;
import org.springframework.web.bind.annotation.*;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.ProcessDefinition;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.zip.ZipInputStream;

@RestController
@RequestMapping("/processes")
@Api(tags = "流程管理")
public class ProcessController {

    private final RepositoryService repositoryService;

    private final RuntimeService runtimeService;

    @Resource
    private  SysSystemProcessMapper sysSystemProcessMapper;
    @ApiOperation(value = "系统下流程列表",notes = "系统下流程列表")
    @PostMapping("processListInSystem")
    public AjaxResult processList(@RequestParam("systemCode")String systemCode){
        List<ProcessDefinition> allProcesses = repositoryService.createProcessDefinitionQuery().list();
        Map<String, ProcessDefinition> latestProcessesMap =
                allProcesses.stream().collect(
                        Collectors.toMap(ProcessDefinition::getKey,
                                i -> i,
                                (processDefinition1, processDefinition2) -> {
                                    if (processDefinition1.getVersion() < processDefinition2.getVersion()) {
                                        return processDefinition2;
                                    } else {
                                        return processDefinition1;
                                    }
                                }));
        List<ProcessDefinition> processDefinitions= latestProcessesMap.values().stream().collect(Collectors.toList());
        List<SysSystemProcess> sysSystemProcesses=sysSystemProcessMapper.selectList(new LambdaQueryWrapper<SysSystemProcess>()
                .eq(SysSystemProcess::getSystemCode,systemCode));
        if (CollectionUtil.isEmpty(sysSystemProcesses)){
            return  AjaxResult.success(new ArrayList<>());
        }
        processDefinitions=processDefinitions.stream().filter(i->sysSystemProcesses.stream().map(SysSystemProcess::getProcessId)
                .collect(Collectors.toList()).contains(i.getDeploymentId())).collect(Collectors.toList());
        List<ProcessDefinitionDetailVO> processDefinitionDetailVOS=new ArrayList<>();
        for (ProcessDefinition processDefinition:processDefinitions){
            ProcessDefinitionDetailVO processDefinitionDetailVO=new ProcessDefinitionDetailVO();
            BeanUtils.copyProperties(processDefinition,processDefinitionDetailVO);
            processDefinitionDetailVOS.add(processDefinitionDetailVO);
        }
        return AjaxResult.success(processDefinitionDetailVOS);
    }



    @Autowired
    public ProcessController(RepositoryService repositoryService, RuntimeService runtimeService) {

        this.repositoryService = repositoryService;
        this.runtimeService = runtimeService;
    }

    @ApiOperation(value = "获取最新流程定义",notes = "获取最新流程定义")
    @GetMapping
    public List getLatestProcessDefinitions() {
        List<ProcessDefinition> allProcesses = repositoryService.createProcessDefinitionQuery().list();
        Map<String, ProcessDefinition> latestProcessesMap =
                allProcesses.stream().collect(
                        Collectors.toMap(ProcessDefinition::getKey,
                                i -> i,
                        (processDefinition1, processDefinition2) -> {
                            if (processDefinition1.getVersion() < processDefinition2.getVersion()) {
                                return processDefinition2;
                            } else {
                                return processDefinition1;
                            }
                        }))
                ;
        List<ProcessDefinition> processDefinitions= latestProcessesMap.values().stream().collect(Collectors.toList());
        List<ProcessDefinitionDetailVO> processDefinitionDetailVOS=new ArrayList<>();
        for (ProcessDefinition processDefinition:processDefinitions){
            ProcessDefinitionDetailVO processDefinitionDetailVO=new ProcessDefinitionDetailVO();
            BeanUtils.copyProperties(processDefinition,processDefinitionDetailVO);
            processDefinitionDetailVOS.add(processDefinitionDetailVO);
        }
        return processDefinitionDetailVOS;
    }


    @GetMapping("startProcess")
    public ProcessInstanceVO startProcess(@RequestParam("processKey") String processKey) {
        ProcessInstance processInstance=runtimeService.startProcessInstanceByKey(processKey);
        ProcessInstanceVO processInstanceVO=new ProcessInstanceVO();
        BeanUtils.copyProperties(processInstance,processInstanceVO);
        return processInstanceVO;
    }

    /*
     * 上传并部署流程定义
     *
     * @param file
     * @return
     * @throws IOException
     */
    @PostMapping(value = "/uploadStreamAndDeployment")
    public AjaxResult uploadStreamAndDeployment(@RequestParam("file") MultipartFile file) throws IOException {
        String fileName = file.getOriginalFilename();
        // 得到输入流（字节流）对象
        InputStream fileInputStream = file.getInputStream();
        // 文件的扩展名
        String extension = FilenameUtils.getExtension(fileName);

        if (extension.equals("zip")) {
            ZipInputStream zip = new ZipInputStream(fileInputStream);
            repositoryService.createDeployment()//初始化流程
                    .addZipInputStream(zip)
                    .deploy();
        } else {
            repositoryService.createDeployment()//初始化流程
                    .addInputStream(fileName, fileInputStream)

                    .deploy();
        }
        return AjaxResult.success();
    }

    @PostMapping(value = "/addDeploymentByString")
    public AjaxResult addDeploymentByString(@RequestBody BPMNDTO stringBPMN) {
        repositoryService.createDeployment()
                .addString("CreateWithBPMNJS.bpmn", stringBPMN.getXml())
                .deploy();
        return AjaxResult.success("成功");
    }

    @GetMapping(value = "/getDefinitionXML")
    public void getProcessDefineXML(HttpServletResponse response,
                                    @RequestParam("deploymentId") String deploymentId,
                                    @RequestParam("resourceName") String resourceName) throws IOException {

        InputStream inputStream = repositoryService.getResourceAsStream(deploymentId, resourceName);
        int count = inputStream.available();
        byte[] bytes = new byte[count];
        response.setContentType("text/xml");
        OutputStream outputStream = response.getOutputStream();
        while (inputStream.read(bytes) != -1) {
            outputStream.write(bytes);
        }
        inputStream.close();
    }
}
